package com.pj.lib.auraClient;

import java.io.IOException;
import java.util.ArrayList;

import com.pj.lib.auraClient.interfaces.OnAuraCasterAPI;
import com.pj.lib.auraClient.interfaces.OnAuraSensitiveUserAPI;
import com.pj.lib.auraClient.interfaces.OnUserAPI;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class AuraService extends Service {
	private static final String TAG = "AuraService";
	
	public final static String PREFS_NAME = "auraPrefs";
	
	public final static String PREFS_KEY_LOGIN = "login";
	public final static String PREFS_KEY_PASSWORD = "password";
	
	public static boolean STARTED = false;
	
	protected static final String FUNCTION_PREFIX_GET = "handleGet";
	protected static final String FUNCTION_PREFIX_SEND = "handleSend";
	
	public enum ConnectionStatus {
		DISCONNECTED, CONNECTED, CONNECTING
	}
	
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // service connection thread
    private AuraServiceConnectionThread mConnectionThread;

    private ArrayList<OnUserAPI> mOnUserAPIListeners = new ArrayList<OnUserAPI>();
    private ArrayList<OnAuraCasterAPI> mOnAuraCasterAPIListeners = new ArrayList<OnAuraCasterAPI>();
    private ArrayList<OnAuraSensitiveUserAPI> mOnAuraSensitiveUserAPIListeners = new ArrayList<OnAuraSensitiveUserAPI>();
    
    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
    	AuraService getService() {
            // Return this instance of LocalService so clients can call public methods
            return AuraService.this;
        }
    }
    
    @Override
	public void onCreate() {
		Log.i(TAG, "oncreate");
	}

	@Override
    public IBinder onBind(Intent intent) {
    	Log.i(TAG, "binding to service");

        return mBinder;
    }

    @Override
	public void onStart(Intent intent, int startId) {
		handleCommand(intent);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// if it isnt redelivery it is started by application so do not auto login
		/*if(flags != START_FLAG_REDELIVERY) {
			
			AuraPreferences.updateString(this, AuraPreferences.KEY_LOGGED, "N");
		} else {
			
		}*/
		Log.i(TAG, "flag: " + flags);
		if(!STARTED)
			handleCommand(intent);
		return START_STICKY;
	}
	
	private void handleCommand(Intent intent) {
		Log.i(TAG, "starting service, intent: " + intent);
		String serverAddress;
		int serverPort;
		Boolean login;
		
		if(intent == null || !intent.hasExtra("serverAddress") || !intent.hasExtra("serverPort")) {
			serverAddress = AuraPreferences.getString(this, AuraPreferences.KEY_ADDRESS);
			serverPort = AuraPreferences.getInt(this, AuraPreferences.KEY_PORT);
			if(AuraPreferences.getString(this, AuraPreferences.KEY_LOGGED).equals("Y"))
				login = true;
			else
				login = false;
		} else {
			serverAddress = intent.getStringExtra("serverAddress");
			serverPort = intent.getIntExtra("serverPort", 4444);
			AuraPreferences.updateString(this, AuraPreferences.KEY_ADDRESS, serverAddress);
			AuraPreferences.updateInt(this, AuraPreferences.KEY_PORT, serverPort);
			login = false;
		}
		
		mConnectionThread = new AuraServiceConnectionThread(this, 
				serverAddress, 
				serverPort);
		if(login) {
			Log.i(TAG, "starting thread with login");
			mConnectionThread.doOnConnected(new Runnable() {
				@Override
				public void run() {
					try {
						mConnectionThread.handleSendLogin(
								AuraPreferences.getString(AuraService.this, AuraPreferences.KEY_LOGIN), 
								AuraPreferences.getString(AuraService.this, AuraPreferences.KEY_PASSWORD));
					} catch (IOException e) {
						Log.e(TAG, "error at sending login: " + e.getMessage());
					}
				}
			});
			mConnectionThread.start();
		} else {
			Log.i(TAG, "starting thread");
			mConnectionThread.start();
		}
		STARTED = true;
	}
    
	
	
	@Override
	public void onDestroy() {
		Log.i(TAG, "closing service");
		AuraPreferences.updateString(this, AuraPreferences.KEY_LOGGED, "N");
	}

	public AuraServiceConnectionThread getConnectionThread() {
		return mConnectionThread; 
	}
	
	
    /**
     * Listeners
     */
    public void addOnUserApiListener(OnUserAPI listener) {
    	mOnUserAPIListeners.add(listener);
    }
    
    public void addOnAuraCasterApiListener(OnAuraCasterAPI listener) {
    	mOnAuraCasterAPIListeners.add(listener);
    }
    public void addOnAuraSensitiveUserApiListener(OnAuraSensitiveUserAPI listener) {
    	mOnAuraSensitiveUserAPIListeners.add(listener);
    }
    
    
    public void fireConnectionStatus(ConnectionStatus status) {
    	for(OnUserAPI listener : mOnUserAPIListeners) {
    		listener.connectionStatus(status);
    	}
    }
    public void fireLoginResult(Boolean result, String description, Integer userId) {
    	for(OnUserAPI listener : mOnUserAPIListeners) {
    		listener.loginResult(result, description, userId);
    	}
    }
    public void fireCreateAccountResult(Boolean result, String description, Integer userId) {
    	for(OnUserAPI listener : mOnUserAPIListeners) {
    		listener.createAccountResult(result, description, userId);
    	}
    }


	
}
